package auth

import (
	"errors"
	"time"

	"golang.org/x/crypto/bcrypt"
)

// Service 认证服务接口
type Service interface {
	// 用户相关
	GetUser(id uint) (*UserDTO, error)
	CreateUser(req *CreateUserRequest) (*UserDTO, error)
	UpdateUser(id uint, req *UpdateUserRequest) (*UserDTO, error)
	DeleteUser(id uint) error
	ListUsers(query *UserQuery) ([]*UserDTO, int64, error)

	// 登录认证
	Login(username, password string) (*TokenInfo, error)
	RefreshToken(refreshToken string) (*TokenInfo, error)

	// 角色相关
	GetRole(id uint) (*RoleDTO, error)
	CreateRole(req *CreateRoleRequest) (*RoleDTO, error)
	UpdateRole(id uint, req *UpdateRoleRequest) (*RoleDTO, error)
	DeleteRole(id uint) error
	ListRoles(query *RoleQuery) ([]*RoleDTO, int64, error)

	// 权限相关
	GetPermission(id uint) (*PermissionDTO, error)
	CreatePermission(req *CreatePermissionRequest) (*PermissionDTO, error)
	UpdatePermission(id uint, req *UpdatePermissionRequest) (*PermissionDTO, error)
	DeletePermission(id uint) error
	ListPermissions(query *PermissionQuery) ([]*PermissionDTO, int64, error)

	// 用户角色管理
	GetUserRoles(userID uint) ([]*RoleDTO, error)
	AssignRolesToUser(userID uint, roleIDs []uint) error

	// 角色权限管理
	GetRolePermissions(roleCode string) ([]*PermissionDTO, error)
	AssignPermissionsToRole(roleCode string, req *AssignPermissionsRequest) error

	// 权限检查
	CheckPermission(userID uint, permissionCode string, resourceCode string) (bool, error)
}

// UserDTO 用户数据传输对象
type UserDTO struct {
	ID          uint      `json:"id"`
	TenantID    uint      `json:"tenant_id"`
	Username    string    `json:"username"`
	Status      int       `json:"status"`
	Description string    `json:"description"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

// RoleDTO 角色数据传输对象
type RoleDTO struct {
	ID          uint      `json:"id"`
	TenantID    uint      `json:"tenant_id"`
	Name        string    `json:"name"`
	Code        string    `json:"code"`
	Status      int       `json:"status"`
	Description string    `json:"description"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

// PermissionDTO 权限数据传输对象
type PermissionDTO struct {
	ID          uint      `json:"id"`
	TenantID    uint      `json:"tenant_id"`
	Name        string    `json:"name"`
	Type        int       `json:"type"`
	Code        string    `json:"code"`
	Icon        string    `json:"icon"`
	Status      int       `json:"status"`
	Description string    `json:"description"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

// TokenInfo 令牌信息
type TokenInfo struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int    `json:"expires_in"`
	TokenType    string `json:"token_type"`
}

// CreateUserRequest 创建用户请求
type CreateUserRequest struct {
	TenantID    uint   `json:"tenant_id" binding:"required"`
	Username    string `json:"username" binding:"required,min=3,max=50"`
	Password    string `json:"password" binding:"required,min=6,max=50"`
	Status      int    `json:"status"`
	Description string `json:"description"`
}

// UpdateUserRequest 更新用户请求
type UpdateUserRequest struct {
	Password    *string `json:"password"`
	Status      *int    `json:"status"`
	Description *string `json:"description"`
}

// CreateRoleRequest 创建角色请求
type CreateRoleRequest struct {
	TenantID    uint   `json:"tenant_id" binding:"required"`
	Name        string `json:"name" binding:"required,min=2,max=50"`
	Code        string `json:"code" binding:"required,min=2,max=50"`
	Status      int    `json:"status"`
	Description string `json:"description"`
}

// UpdateRoleRequest 更新角色请求
type UpdateRoleRequest struct {
	Name        *string `json:"name"`
	Status      *int    `json:"status"`
	Description *string `json:"description"`
}

// CreatePermissionRequest 创建权限请求
type CreatePermissionRequest struct {
	TenantID    uint   `json:"tenant_id" binding:"required"`
	Name        string `json:"name" binding:"required,min=2,max=50"`
	Type        int    `json:"type"`
	Code        string `json:"code" binding:"required,min=2,max=50"`
	Icon        string `json:"icon"`
	Status      int    `json:"status"`
	Description string `json:"description"`
}

// UpdatePermissionRequest 更新权限请求
type UpdatePermissionRequest struct {
	Name        *string `json:"name"`
	Type        *int    `json:"type"`
	Icon        *string `json:"icon"`
	Status      *int    `json:"status"`
	Description *string `json:"description"`
}

// AssignPermissionsRequest 分配权限请求
type AssignPermissionsRequest struct {
	PermissionCodes []string `json:"permission_codes" binding:"required"`
	ResourceCode    string   `json:"resource_code" binding:"required"`
}

// DefaultService 默认服务实现
type DefaultService struct {
	repo Repository
	jwt  JWTService
}

// NewService 创建认证服务
func NewService(repo Repository, jwt JWTService) Service {
	return &DefaultService{
		repo: repo,
		jwt:  jwt,
	}
}

// GetUser 获取用户信息
func (s *DefaultService) GetUser(id uint) (*UserDTO, error) {
	user, err := s.repo.GetUserByID(id)
	if err != nil {
		return nil, err
	}
	return convertUserToDTO(user), nil
}

// CreateUser 创建用户
func (s *DefaultService) CreateUser(req *CreateUserRequest) (*UserDTO, error) {
	// 密码加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	user := &User{
		TenantID:    req.TenantID,
		Username:    req.Username,
		Password:    string(hashedPassword),
		Status:      req.Status,
		Description: req.Description,
	}

	if err := s.repo.CreateUser(user); err != nil {
		return nil, err
	}

	return convertUserToDTO(user), nil
}

// UpdateUser 更新用户
func (s *DefaultService) UpdateUser(id uint, req *UpdateUserRequest) (*UserDTO, error) {
	user, err := s.repo.GetUserByID(id)
	if err != nil {
		return nil, err
	}

	// 更新密码
	if req.Password != nil {
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(*req.Password), bcrypt.DefaultCost)
		if err != nil {
			return nil, err
		}
		user.Password = string(hashedPassword)
	}

	// 更新状态
	if req.Status != nil {
		user.Status = *req.Status
	}

	// 更新描述
	if req.Description != nil {
		user.Description = *req.Description
	}

	if err := s.repo.UpdateUser(user); err != nil {
		return nil, err
	}

	return convertUserToDTO(user), nil
}

// DeleteUser 删除用户
func (s *DefaultService) DeleteUser(id uint) error {
	return s.repo.DeleteUser(id)
}

// ListUsers 查询用户列表
func (s *DefaultService) ListUsers(query *UserQuery) ([]*UserDTO, int64, error) {
	users, total, err := s.repo.ListUsers(query)
	if err != nil {
		return nil, 0, err
	}

	userDTOs := make([]*UserDTO, len(users))
	for i, user := range users {
		userDTOs[i] = convertUserToDTO(user)
	}

	return userDTOs, total, nil
}

// Login 用户登录
func (s *DefaultService) Login(username, password string) (*TokenInfo, error) {
	// 获取用户
	user, err := s.repo.GetUserByUsername(username)
	if err != nil {
		if errors.Is(err, ErrUserNotFound) {
			return nil, ErrInvalidPassword // 为了安全，不区分用户不存在和密码错误
		}
		return nil, err
	}

	// 检查用户状态
	if user.Status != 1 {
		return nil, ErrUserDisabled
	}

	// 验证密码
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		return nil, ErrInvalidPassword
	}

	// 生成令牌
	return s.jwt.GenerateToken(user.ID, user.TenantID, user.Username)
}

// RefreshToken 刷新令牌
func (s *DefaultService) RefreshToken(refreshToken string) (*TokenInfo, error) {
	return s.jwt.RefreshToken(refreshToken)
}

// GetRole 获取角色信息
func (s *DefaultService) GetRole(id uint) (*RoleDTO, error) {
	role, err := s.repo.GetRoleByID(id)
	if err != nil {
		return nil, err
	}
	return convertRoleToDTO(role), nil
}

// CreateRole 创建角色
func (s *DefaultService) CreateRole(req *CreateRoleRequest) (*RoleDTO, error) {
	role := &Role{
		TenantID:    req.TenantID,
		Name:        req.Name,
		Code:        req.Code,
		Status:      req.Status,
		Description: req.Description,
	}

	if err := s.repo.CreateRole(role); err != nil {
		return nil, err
	}

	return convertRoleToDTO(role), nil
}

// UpdateRole 更新角色
func (s *DefaultService) UpdateRole(id uint, req *UpdateRoleRequest) (*RoleDTO, error) {
	role, err := s.repo.GetRoleByID(id)
	if err != nil {
		return nil, err
	}

	if req.Name != nil {
		role.Name = *req.Name
	}

	if req.Status != nil {
		role.Status = *req.Status
	}

	if req.Description != nil {
		role.Description = *req.Description
	}

	if err := s.repo.UpdateRole(role); err != nil {
		return nil, err
	}

	return convertRoleToDTO(role), nil
}

// DeleteRole 删除角色
func (s *DefaultService) DeleteRole(id uint) error {
	return s.repo.DeleteRole(id)
}

// ListRoles 查询角色列表
func (s *DefaultService) ListRoles(query *RoleQuery) ([]*RoleDTO, int64, error) {
	roles, total, err := s.repo.ListRoles(query)
	if err != nil {
		return nil, 0, err
	}

	roleDTOs := make([]*RoleDTO, len(roles))
	for i, role := range roles {
		roleDTOs[i] = convertRoleToDTO(role)
	}

	return roleDTOs, total, nil
}

// GetPermission 获取权限信息
func (s *DefaultService) GetPermission(id uint) (*PermissionDTO, error) {
	permission, err := s.repo.GetPermissionByID(id)
	if err != nil {
		return nil, err
	}
	return convertPermissionToDTO(permission), nil
}

// CreatePermission 创建权限
func (s *DefaultService) CreatePermission(req *CreatePermissionRequest) (*PermissionDTO, error) {
	permission := &Permission{
		TenantID:    req.TenantID,
		Name:        req.Name,
		Type:        req.Type,
		Code:        req.Code,
		Icon:        req.Icon,
		Status:      req.Status,
		Description: req.Description,
	}

	if err := s.repo.CreatePermission(permission); err != nil {
		return nil, err
	}

	return convertPermissionToDTO(permission), nil
}

// UpdatePermission 更新权限
func (s *DefaultService) UpdatePermission(id uint, req *UpdatePermissionRequest) (*PermissionDTO, error) {
	permission, err := s.repo.GetPermissionByID(id)
	if err != nil {
		return nil, err
	}

	if req.Name != nil {
		permission.Name = *req.Name
	}

	if req.Type != nil {
		permission.Type = *req.Type
	}

	if req.Icon != nil {
		permission.Icon = *req.Icon
	}

	if req.Status != nil {
		permission.Status = *req.Status
	}

	if req.Description != nil {
		permission.Description = *req.Description
	}

	if err := s.repo.UpdatePermission(permission); err != nil {
		return nil, err
	}

	return convertPermissionToDTO(permission), nil
}

// DeletePermission 删除权限
func (s *DefaultService) DeletePermission(id uint) error {
	return s.repo.DeletePermission(id)
}

// ListPermissions 查询权限列表
func (s *DefaultService) ListPermissions(query *PermissionQuery) ([]*PermissionDTO, int64, error) {
	permissions, total, err := s.repo.ListPermissions(query)
	if err != nil {
		return nil, 0, err
	}

	permissionDTOs := make([]*PermissionDTO, len(permissions))
	for i, permission := range permissions {
		permissionDTOs[i] = convertPermissionToDTO(permission)
	}

	return permissionDTOs, total, nil
}

// GetUserRoles 获取用户角色
func (s *DefaultService) GetUserRoles(userID uint) ([]*RoleDTO, error) {
	roles, err := s.repo.GetUserRoles(userID)
	if err != nil {
		return nil, err
	}

	roleDTOs := make([]*RoleDTO, len(roles))
	for i, role := range roles {
		roleDTOs[i] = convertRoleToDTO(role)
	}

	return roleDTOs, nil
}

// AssignRolesToUser 为用户分配角色
func (s *DefaultService) AssignRolesToUser(userID uint, roleIDs []uint) error {
	return s.repo.AssignRolesToUser(userID, roleIDs)
}

// GetRolePermissions 获取角色权限
func (s *DefaultService) GetRolePermissions(roleCode string) ([]*PermissionDTO, error) {
	permissions, err := s.repo.GetRolePermissions(roleCode)
	if err != nil {
		return nil, err
	}

	permissionDTOs := make([]*PermissionDTO, len(permissions))
	for i, permission := range permissions {
		permissionDTOs[i] = convertPermissionToDTO(permission)
	}

	return permissionDTOs, nil
}

// AssignPermissionsToRole 为角色分配权限
func (s *DefaultService) AssignPermissionsToRole(roleCode string, req *AssignPermissionsRequest) error {
	return s.repo.AssignPermissionsToRole(roleCode, req.PermissionCodes, req.ResourceCode)
}

// CheckPermission 检查用户是否有指定权限
func (s *DefaultService) CheckPermission(userID uint, permissionCode string, resourceCode string) (bool, error) {
	// 获取用户角色
	roles, err := s.repo.GetUserRoles(userID)
	if err != nil {
		return false, err
	}

	// 检查每个角色是否有权限
	for _, role := range roles {
		// 获取角色权限
		permissions, err := s.repo.GetRolePermissions(role.Code)
		if err != nil {
			return false, err
		}

		// 检查是否包含指定权限
		for _, permission := range permissions {
			if permission.Code == permissionCode {
				return true, nil
			}
		}
	}

	return false, nil
}

// 辅助函数：转换用户实体到DTO
func convertUserToDTO(user *User) *UserDTO {
	return &UserDTO{
		ID:          user.ID,
		TenantID:    user.TenantID,
		Username:    user.Username,
		Status:      user.Status,
		Description: user.Description,
		CreatedAt:   user.CreatedAt,
		UpdatedAt:   user.UpdatedAt,
	}
}

// 辅助函数：转换角色实体到DTO
func convertRoleToDTO(role *Role) *RoleDTO {
	return &RoleDTO{
		ID:          role.ID,
		TenantID:    role.TenantID,
		Name:        role.Name,
		Code:        role.Code,
		Status:      role.Status,
		Description: role.Description,
		CreatedAt:   role.CreatedAt,
		UpdatedAt:   role.UpdatedAt,
	}
}

// 辅助函数：转换权限实体到DTO
func convertPermissionToDTO(permission *Permission) *PermissionDTO {
	return &PermissionDTO{
		ID:          permission.ID,
		TenantID:    permission.TenantID,
		Name:        permission.Name,
		Type:        permission.Type,
		Code:        permission.Code,
		Icon:        permission.Icon,
		Status:      permission.Status,
		Description: permission.Description,
		CreatedAt:   permission.CreatedAt,
		UpdatedAt:   permission.UpdatedAt,
	}
}
